import * as THREE from '../../build/three.module.js';
import Stats from '../../jsm/libs/stats.module.js';

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x050505);
scene.fog = new THREE.Fog(0x050505, 2000, 3500);

const camera = new THREE.PerspectiveCamera(30, innerWidth / innerHeight, 1, 10000);
camera.position.z = 2750;

const al = new THREE.AmbientLight(0x444444);
scene.add(al);

const dl1 = new THREE.DirectionalLight(0xffffff);
dl1.position.set(1, 1, 1);
scene.add(dl1);

const dl2 = new THREE.DirectionalLight(0xffffff);
dl2.position.set(0, -1, 0);
scene.add(dl2);

const trangles = 160000, // 三角形总数
      points = [], // 所有三角顶点
      normals = [], // 各个顶点法线
      colors = [], // 各顶点着色
      color = new THREE.Color(), // 色彩缓存
      gmt = new THREE.BufferGeometry(), // 几何体缓存
      n = 800, n2 = n / 2, // 立方体定位
      d = 12, d2 = d / 2, // 单个三角形尺寸
      pA = new THREE.Vector3(), // 单个三角形三个顶点缓存
      pB = new THREE.Vector3(),
      pC = new THREE.Vector3(),
      cb = new THREE.Vector3(), // 三角面法线缓存
      ab = new THREE.Vector3();

for(let i = 0; i < trangles; i += 1) {
  // 三角面中心定位
  const x = Math.random() * n - n2;
  const y = Math.random() * n - n2;
  const z = Math.random() * n - n2;

  // 围绕中心构建三个顶点坐标
  const ax = x + Math.random() * d - d2;
  const ay = y + Math.random() * d - d2;
  const az = z + Math.random() * d - d2;
  
  const bx = x + Math.random() * d - d2;
  const by = y + Math.random() * d - d2;
  const bz = z + Math.random() * d - d2;
  
  const cx = x + Math.random() * d - d2;
  const cy = y + Math.random() * d - d2;
  const cz = z + Math.random() * d - d2;

  // 保存顶点坐标
  points.push(ax, ay, az);
  points.push(bx, by, bz);
  points.push(cx, cy, cz);

  // 获取三角面法向量
  pA.set(ax, ay, az); // 三角面三个顶点坐标设置
  pB.set(bx, by, bz);
  pC.set(cx, cy, cz);
  cb.subVectors(pC, pB); // 获取同一顶点发出的两个向量
  ab.subVectors(pA, pB);
  cb.cross(ab); // 同源向量叉积
  cb.normalize(); // 叉积的发现，即面法线

  // 保存面法线
  normals.push(cb.x, cb.y, cb.z); // 三次三个顶点，法线相同
  normals.push(cb.x, cb.y, cb.z);
  normals.push(cb.x, cb.y, cb.z);

  // 顶点着色
  const vx = (x / n) + .5; // 取值范围[0, 1]
  const vy = (y / n) + .5;
  const vz = (z / n) + .5;

  color.setRGB(vx, vy, vz); // 根据三角面定位设置rgb值

  // 保存三顶点颜色值
  colors.push(color.r, color.g, color.b);
  colors.push(color.r, color.g, color.b);
  colors.push(color.r, color.g, color.b);
}

// 将几何体数据交给gpu后清除原数据缓存
function dispose() {
  this.array = null;
}

// 设置 BufferGeometry 的属性
gmt.setAttribute('position', new THREE.Float32BufferAttribute(points, 3).onUpload(dispose));
gmt.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3).onUpload(dispose));
gmt.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3).onUpload(dispose));
gmt.computeBoundingSphere();

const mtl = new THREE.MeshPhongMaterial({
  color: 0xaaaaaa,
  specular: 0xffffff,
  shininess:250,
  side: THREE.DoubleSide,
  vertexColors: THREE.VertexColors // 启动顶点着色
});

const mesh = new THREE.Mesh(gmt, mtl);
scene.add(mesh);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

const stats = new Stats();
document.body.appendChild(stats.dom);

const render = () => {
  const time = Date.now() * .001;
  mesh.rotation.x = time * .25;
  mesh.rotation.y = time * .5;

  renderer.render(scene, camera);
}

const animate = () => {
  requestAnimationFrame(animate);

  render();
  stats.update();
}
animate();

const handleWindowResize = () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, innerHeight);
}
window.addEventListener('resize', handleWindowResize, false);